package com.tools.service.workflow.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tools.mapper.workflow.FlowDefinitionMapper;
import com.tools.pojo.workflow.bo.FlowNode;
import com.tools.pojo.workflow.po.FlowDefinition;
import com.tools.pojo.workflow.po.FlowTransition;
import com.tools.service.workflow.FlowDefinitionService;
import com.tools.service.workflow.FlowNodeService;
import com.tools.service.workflow.FlowTransitionService;
import com.tools.utils.JsonUtil;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service("flowDefinition")
@RequiredArgsConstructor
public class FlowDefinitionServiceImpl extends ServiceImpl<FlowDefinitionMapper, FlowDefinition> implements FlowDefinitionService {

    private final ObjectMapper objectMapper;
    private final FlowNodeService flowNodeService;
    private final FlowTransitionService flowTransitionService;
    
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    
    // Redis缓存键前缀
    private static final String FLOW_DEFINITION_CACHE_PREFIX = "flow:definition:";
    private static final String FLOW_NODES_CACHE_PREFIX = "flow:nodes:";
    private static final String FLOW_TRANSITIONS_CACHE_PREFIX = "flow:transitions:";
    private static final long CACHE_EXPIRE_TIME = 60; // 缓存过期时间（分钟）

    /**
     * 根据流程编码获取流程定义（优先从缓存获取）
     */
    @Override
    public FlowDefinition getByCode(String flowCode) {
        // 先尝试从缓存获取最新激活版本
        String cacheKey = FLOW_DEFINITION_CACHE_PREFIX + "latest:" + flowCode;
        Object data = redisTemplate.opsForValue().get(cacheKey);
        FlowDefinition cachedDefinition;
        if (data instanceof Map) {
            try {
                cachedDefinition = JsonUtil.fromJson(JSONUtil.toJsonStr(data), new TypeReference<>() {
                });
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
        } else if (data instanceof FlowDefinition) {
            cachedDefinition = (FlowDefinition) data;
        }else{
            // 缓存未命中，从数据库查询
            cachedDefinition = lambdaQuery()
                    .eq(FlowDefinition::getFlowCode, flowCode)
                    .eq(FlowDefinition::getStatus, 1)
                    .orderByDesc(FlowDefinition::getVersion)
                    .last("LIMIT 1")
                    .one();
        }

        

        
        // 放入缓存
        if (cachedDefinition != null) {
            redisTemplate.opsForValue().set(cacheKey, cachedDefinition, CACHE_EXPIRE_TIME, TimeUnit.MINUTES);
        }
        
        return cachedDefinition;
    }
    
    /**
     * 根据流程代码和版本获取流程定义
     */
    @Override
    public FlowDefinition getByCodeAndVersion(String flowCode, Integer version) {
        String cacheKey = FLOW_DEFINITION_CACHE_PREFIX + flowCode + ":v" + version;
        FlowDefinition cachedDefinition = (FlowDefinition) redisTemplate.opsForValue().get(cacheKey);
        if (cachedDefinition != null) {
            return cachedDefinition;
        }
        
        FlowDefinition definition = lambdaQuery()
                .eq(FlowDefinition::getFlowCode, flowCode)
                .eq(FlowDefinition::getVersion, version)
                .one();
        
        if (definition != null) {
            redisTemplate.opsForValue().set(cacheKey, definition, CACHE_EXPIRE_TIME, TimeUnit.MINUTES);
        }
        
        return definition;
    }

    /**
     * 解析流程配置
     */
    @Override
    public List<Map<String, Object>> parseFlowConfig(String configJson) {
        try {
            if (configJson == null || configJson.trim().isEmpty()) {
                return List.of();
            }
            return objectMapper.readValue(configJson, new TypeReference<>() {
            });
        } catch (Exception e) {
            log.error("解析流程配置失败", e);
            throw new RuntimeException("流程配置格式错误", e);
        }
    }

    /**
     * 获取所有启用的流程定义
     */
    @Override
    public List<FlowDefinition> getActiveFlows() {
        return lambdaQuery()
                .eq(FlowDefinition::getStatus, 1)
                .list();
    }
    
    /**
     * 创建新版本流程定义
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public FlowDefinition createNewVersion(FlowDefinition flowDefinition, List<FlowNode> nodes, List<FlowTransition> transitions) {
        // 获取当前最新版本
        FlowDefinition latest = lambdaQuery()
                .eq(FlowDefinition::getFlowCode, flowDefinition.getFlowCode())
                .orderByDesc(FlowDefinition::getVersion)
                .one();
        
        // 计算新版本号
        Integer newVersion = latest != null ? latest.getVersion() + 1 : 1;
        flowDefinition.setVersion(newVersion);
        flowDefinition.setStatus(0); // 新建版本默认未激活
        
        // 保存流程定义
        save(flowDefinition);
        
        // 保存节点和连线
        for (FlowNode node : nodes) {
            node.setFlowDefinitionId(flowDefinition.getId());
            flowNodeService.save(node);
        }
        
        for (FlowTransition transition : transitions) {
            transition.setFlowDefinitionId(flowDefinition.getId());
            flowTransitionService.save(transition);
        }
        
        log.info("创建流程定义新版本成功: {} v{}", flowDefinition.getFlowCode(), newVersion);
        return flowDefinition;
    }
    
    /**
     * 发布流程定义
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean publishDefinition(Long definitionId) {
        FlowDefinition definition = getById(definitionId);
        if (definition == null) {
            log.error("流程定义不存在: {}", definitionId);
            return false;
        }
        
        // 停用同一流程代码的所有已激活版本
        lambdaUpdate()
                .eq(FlowDefinition::getFlowCode, definition.getFlowCode())
                .eq(FlowDefinition::getStatus, 1)
                .set(FlowDefinition::getStatus, 2) // 2表示已停用
                .update();
        
        // 激活当前版本
        definition.setStatus(1);
        boolean result = updateById(definition);
        
        if (result) {
            // 清除缓存，确保下次获取最新版本
            clearDefinitionCache(definition.getFlowCode());
            // 同步到缓存
            syncDefinitionToCache(definitionId);
            log.info("流程定义发布成功: {} v{}", definition.getFlowCode(), definition.getVersion());
        }
        
        return result;
    }
    
    /**
     * 停用流程定义
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deactivateDefinition(Long definitionId) {
        FlowDefinition definition = getById(definitionId);
        if (definition == null) {
            log.error("流程定义不存在: {}", definitionId);
            return false;
        }
        
        definition.setStatus(2); // 2表示已停用
        boolean result = updateById(definition);
        
        if (result) {
            // 清除缓存
            clearDefinitionCache(definition.getFlowCode());
            log.info("流程定义停用成功: {} v{}", definition.getFlowCode(), definition.getVersion());
        }
        
        return result;
    }
    
    /**
     * 获取流程定义的版本历史
     */
    @Override
    public List<FlowDefinition> getVersionHistory(String flowCode) {
        return lambdaQuery()
                .eq(FlowDefinition::getFlowCode, flowCode)
                .orderByDesc(FlowDefinition::getVersion)
                .list();
    }
    
    /**
     * 同步流程定义变更到缓存
     */
    @Override
    public void syncDefinitionToCache(Long definitionId) {
        FlowDefinition definition = getById(definitionId);
        if (definition == null) {
            return;
        }
        
        // 缓存流程定义
        String defCacheKey = FLOW_DEFINITION_CACHE_PREFIX + definition.getFlowCode() + ":v" + definition.getVersion();
        redisTemplate.opsForValue().set(defCacheKey, definition, CACHE_EXPIRE_TIME, TimeUnit.MINUTES);
        
        // 如果是激活状态，还需缓存为最新版本
        if (definition.getStatus() == 1) {
            String latestCacheKey = FLOW_DEFINITION_CACHE_PREFIX + "latest:" + definition.getFlowCode();
            redisTemplate.opsForValue().set(latestCacheKey, definition, CACHE_EXPIRE_TIME, TimeUnit.MINUTES);
        }
        
        // 缓存节点信息
        List<FlowNode> nodes = flowNodeService.getNodesByFlowDefinitionId(definitionId);
        String nodesCacheKey = FLOW_NODES_CACHE_PREFIX + definitionId;
        redisTemplate.opsForValue().set(nodesCacheKey, nodes, CACHE_EXPIRE_TIME, TimeUnit.MINUTES);
        
        // 缓存连线信息
        List<FlowTransition> transitions = flowTransitionService.getTransitionsByFlowDefinitionId(definitionId);
        String transitionsCacheKey = FLOW_TRANSITIONS_CACHE_PREFIX + definitionId;
        redisTemplate.opsForValue().set(transitionsCacheKey, transitions, CACHE_EXPIRE_TIME, TimeUnit.MINUTES);
        
        log.info("流程定义同步到缓存成功: {} v{}", definition.getFlowCode(), definition.getVersion());
    }
    
    /**
     * 清除流程定义相关缓存
     */
    private void clearDefinitionCache(String flowCode) {
        // 清除最新版本缓存
        String latestCacheKey = FLOW_DEFINITION_CACHE_PREFIX + "latest:" + flowCode;
        redisTemplate.delete(latestCacheKey);
        
        // 清除所有版本缓存（可以使用模式匹配删除，这里简化处理）
        // 实际应用中可以使用Redis的keys或scan命令查找并删除
        log.info("流程定义缓存已清除: {}", flowCode);
    }
}
